// 顶部：仅类型导入
import type { IParams, IRequestConfig, IRequestData, IRequestParams, RequestError, SSEvent } from "./request";
import { CONTENT_TYPE, ERROR, HEADER, METHOD, RESPONSE_TYPE, TYPE } from "./config";
import Logger, { ILogger } from "../logger";
import _xmlHttpRequest from "./_xmlHttpRequest";
import _fetch from "./_fetch";
import _axios from "./_axios";

export type {
    IParams, IRequestData, IRequestParams, RequestError, SSEvent
}

class RequestData implements IRequestData {
    private logger: ILogger;
    private readonly requestType: string;
    private readonly requestParams: IParams;
    private requestInstance: any

    private errorHandler?: (error: RequestError) => void;
    private static globalErrorHandler?: (error: RequestError) => void;
    private static globalSSEHandler?: (evt: any) => void;
    private static sseParserFactory?: (onEvent: (evt: any) => void) => any;

    static setGlobalErrorHandler(handler: (error: RequestError) => void) {
        RequestData.globalErrorHandler = handler;
    }

    /**
     * 注入 SSE 解析器工厂（来自 eventsource-parser 的 createParser）
     */
    static setSSEParser(factory: (onEvent: (evt: any) => void) => any) {
        RequestData.sseParserFactory = factory;
    }

    static Type = TYPE
    static Header = HEADER
    static ContentType = CONTENT_TYPE
    static ResponseType = RESPONSE_TYPE
    static Method = METHOD
    static Error = ERROR

    constructor(params?: IRequestParams) {
        params = params || {};
        this.logger = new Logger('request', params.loggerLevel);
        this.requestType = params.type ?? TYPE.Axios;
        this.requestParams = {
            loggerLevel: params.loggerLevel,
            method: METHOD.Get,
            url: "",
            requestBody: undefined,
            headers: [],
            async: true,
            responseType: RESPONSE_TYPE.Json,
        }
        // 支持在构造参数中传入 onError（避免类型不兼容，用 any 读取）
        const onError = (params as any)?.onError;
        if (typeof onError === 'function') {
            this.errorHandler = onError;
        }
    }

    private handleError(error: RequestError): void {
        const enriched: RequestError = {
            code: error.code,
            msg: error.msg,
            method: error.method ?? this.requestParams.method,
            url: error.url ?? this.requestParams.url,
            params: error.params ?? this.requestParams.requestBody,
            headers: error.headers ?? this.requestParams.headers,
            error: error.error
        };

        try {
            if (RequestData.globalErrorHandler) {
                RequestData.globalErrorHandler(enriched);
                return;
            }
            if (this.errorHandler) {
                this.errorHandler(enriched);
                return;
            }
        } catch (e) {
            this.logger.error('handleError() custom handler threw', e as any);
        }
        this.logger.error('handleError()', enriched);
    }

    async get<T>(url: string, requestBody?: object):
        Promise<T> {
        this.requestParams.method = METHOD.Get;
        return this.executeRequest<T>(url, requestBody)
    }

    async post<T>(url: string, requestBody?: object):
        Promise<T> {
        this.requestParams.method = METHOD.Post;
        return this.executeRequest<T>(url, requestBody)
    }

    async delete<T>(url: string, requestBody?: object): Promise<T> {
        this.requestParams.method = METHOD.Delete;
        return this.executeRequest<T>(url, requestBody)
    }

    async put<T>(url: string, requestBody?: object):
        Promise<T> {
        this.requestParams.method = METHOD.Put;
        return this.executeRequest<T>(url, requestBody)
    }

    /**
     * 发送 GET 流式请求
     * @param url - 请求地址
     * @param body - 请求体（可选）
     * @returns 返回指定类型的 Promise
     */
    async getStream<T>(url: string, body?: object): Promise<T> {
        this.requestParams.method = METHOD.Get;
        return this.executeRequest<T>(url, body)
    }

    /**
     * 发送 POST 流式请求
     * @param url - 请求地址
     * @param body - 请求体（可选）
     * @returns 返回指定类型的 Promise
     */
    async postStream<T>(url: string, body?: object): Promise<T> {
        this.requestParams.method = METHOD.Post;
        return this.executeRequest<T>(url, body)
    }

    /**
     * 执行请求的核心方法
     */
    abortRequest() {
        if (this.requestInstance) {
            if (this.requestType === TYPE.Axios) {
                this.requestInstance.cancel('Operation canceled by the user.');
            } else {
                this.requestInstance.abort();
            }
        } else {
            this.logger.error('abortRequest()', '未获取到请求实例')
        }
    }

    handleAbort(callback: () => void) {
        callback();
    }

    setHeader(name: string, value: string) {
        const index = this.requestParams.headers.findIndex(m => m.name === name);
        if (index >= 0) this.requestParams.headers[index].value = value;
        else this.requestParams.headers.push({ name, value });
    }

    setHeaderBearer(value: string) {
        const name = HEADER.Authorization;
        const data = `Bearer ${value}`;
        const index = this.requestParams.headers.findIndex(m => m.name === name);
        if (index >= 0) this.requestParams.headers[index].value = data;
        else this.requestParams.headers.push({ name, value: data });

    }

    setHeaderBasic(value: string) {
        const name = HEADER.Authorization;
        const data = `Basic ${value}`;
        const index = this.requestParams.headers.findIndex(m => m.name === name);
        if (index >= 0) this.requestParams.headers[index].value = data;
        else this.requestParams.headers.push({ name, value: data });
    }

    setAsync(value: boolean) {
        this.requestParams.async = value;
    }

    setTimeout(time: number) {
        this.requestParams.timeout = time;
    }

    setResponseType(responseType: XMLHttpRequestResponseType | 'stream') {
        this.requestParams.responseType = responseType;
    }

    setRequest(request: any) {
        this.requestParams.request = request;
    }

    /**
     * 设置请求配置
     * @param config - 请求配置对象
     */
    setRequestConfig(config: IRequestConfig) {
        this.requestParams.requestConfig = config;
    }

    setErrorHandler(handler: (error: RequestError) => void) {
        this.errorHandler = handler;
    }

    /**
     * 执行请求的核心方法
     */
    private executeRequest<T>(url: string, requestBody?: object): Promise<T> {
        this.requestParams.url = url;
        if (requestBody) this.requestParams.requestBody = requestBody;
        if (this.requestType === TYPE.Xml) {
            return _xmlHttpRequest<T>(this.requestParams, {
                requestInstance: (requestInstance) => this.requestInstance = requestInstance,
                handleAbort: () => this.handleAbort,
                handleError: (error) => this.handleError(error),
                handleSSEEvent: (evt) => {
                    try { RequestData.globalSSEHandler?.(evt); } catch (e) { this.logger.error('handleSSEEvent() custom handler threw', e as any); }
                },
                sseParserFactory: RequestData.sseParserFactory ? (onEvent) => RequestData.sseParserFactory!(onEvent) : undefined,
            });
        } else if (this.requestType === TYPE.Fetch) {
            return _fetch<T>(this.requestParams, {
                requestInstance: (requestInstance) => this.requestInstance = requestInstance,
                handleAbort: () => this.handleAbort,
                handleError: (error) => this.handleError(error),
                handleSSEEvent: (evt) => {
                    try { RequestData.globalSSEHandler?.(evt); } catch (e) { this.logger.error('handleSSEEvent() custom handler threw', e as any); }
                },
                sseParserFactory: RequestData.sseParserFactory ? (onEvent) => RequestData.sseParserFactory!(onEvent) : undefined,
            });
        } else if (this.requestType === TYPE.Axios) {
            return _axios<T>(this.requestParams, {
                requestInstance: (requestInstance) => this.requestInstance = requestInstance,
                handleAbort: () => this.handleAbort,
                handleError: (error) => this.handleError(error),
                handleSSEEvent: (evt) => {
                    try { RequestData.globalSSEHandler?.(evt); } catch (e) { this.logger.error('handleSSEEvent() custom handler threw', e as any); }
                },
                sseParserFactory: RequestData.sseParserFactory ? (onEvent) => RequestData.sseParserFactory!(onEvent) : undefined,
            });
        }
        throw new Error(`Unsupported request type: ${this.requestType}`);
    }
}


export default RequestData
